/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * FeatureConfigurationPanel.java
 *
 * Created on Nov 25, 2009, 3:52:48 PM
 */
package wekinator;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import wekinator.FeatureConfiguration.WindowType;
import wekinator.util.Util;

/**
 *
 * @author rebecca
 */
public class FeatureConfigurationPanel extends javax.swing.JPanel {

    protected FeatureConfigurationMetaFrame mf = null;
    protected HidSetup hidSetup = null;
    protected HashMap<String, ArrayList<LinkedList<MetaFeature>>> metaFeatureMatrix = null;

    protected void setMetaFeatureMatrix(HashMap<String, ArrayList<LinkedList<MetaFeature>>> m) {
        metaFeatureMatrix = m;
    }

    /** Creates new form FeatureConfigurationPanel */
    public FeatureConfigurationPanel() {
        initComponents();
        //    setFormFromConfiguration(new FeatureConfiguration
        setHidSetup(hidSetup);
        clearForm();
        updateCustomChuck();
        WekinatorInstance.getWekinatorInstance().getConfiguration().addPropertyChangeListener(new PropertyChangeListener() {

            public void propertyChange(PropertyChangeEvent pce) {
                chuckConfigurationPropertyChanged(pce);
            }
        });
    }

    private void chuckConfigurationPropertyChanged(PropertyChangeEvent pce) {
        if (pce.getPropertyName().equals(ChuckConfiguration.PROP_NUMCUSTOMCHUCKFEATURES)) {
            updateCustomChuck();
        }
    }

    private void updateCustomChuck() {
        ChuckConfiguration c = WekinatorInstance.getWekinatorInstance().getConfiguration();
        if (c != null) {
            if (c.isCustomChuckFeatureExtractorEnabled()) {
                labelNumCustomChuckFeatures.setText("" + c.getNumCustomChuckFeaturesExtracted());
                checkCustomChuck.setEnabled(true);
                checkCustomChuck.setSelected(true);
                labelNumCustomChuckFeatures.setEnabled(true);
                labelCustomChuck2.setEnabled(true);
            } else {
                labelNumCustomChuckFeatures.setText("0");
                checkCustomChuck.setEnabled(false);
                checkCustomChuck.setSelected(false);
                labelNumCustomChuckFeatures.setEnabled(false);
                labelCustomChuck2.setEnabled(false);

            }
        }

    }

    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        buttonGroup1 = new javax.swing.ButtonGroup();
        jPanel1 = new javax.swing.JPanel();
        checkFFT = new javax.swing.JCheckBox();
        checkRMS = new javax.swing.JCheckBox();
        checkCentroid = new javax.swing.JCheckBox();
        checkFlux = new javax.swing.JCheckBox();
        checkRolloff = new javax.swing.JCheckBox();
        jLabel6 = new javax.swing.JLabel();
        textAudioRate = new javax.swing.JFormattedTextField();
        jLabel3 = new javax.swing.JLabel();
        textFftSize = new javax.swing.JFormattedTextField();
        jLabel4 = new javax.swing.JLabel();
        textWindowSize = new javax.swing.JFormattedTextField();
        jLabel5 = new javax.swing.JLabel();
        comboWindowType = new javax.swing.JComboBox();
        checkTrackpad = new javax.swing.JCheckBox();
        checkMotion = new javax.swing.JCheckBox();
        checkHid = new javax.swing.JCheckBox();
        jButton1 = new javax.swing.JButton();
        labelHidDescription = new javax.swing.JLabel();
        checkCustomChuck = new javax.swing.JCheckBox();
        labelCustomChuck2 = new javax.swing.JLabel();
        checkCustomOSC = new javax.swing.JCheckBox();
        textNumCustomOSCFeatures = new javax.swing.JFormattedTextField();
        jLabel7 = new javax.swing.JLabel();
        checkWebcam = new javax.swing.JCheckBox();
        radioWebcamEdge = new javax.swing.JRadioButton();
        radioWebcamColor = new javax.swing.JRadioButton();
        buttonLoad = new javax.swing.JButton();
        buttonSave = new javax.swing.JButton();
        buttonUndo = new javax.swing.JButton();
        buttonGo = new javax.swing.JButton();
        textMotionExtractionRate = new javax.swing.JFormattedTextField();
        jLabel1 = new javax.swing.JLabel();
        labelFeatureStatus = new javax.swing.JLabel();
        buttonAddMeta = new javax.swing.JButton();
        labelNumCustomChuckFeatures = new javax.swing.JLabel();

        jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder("Chuck audio input features"));

        checkFFT.setFont(new java.awt.Font("Lucida Grande", 0, 12));
        checkFFT.setText("FFT");

        checkRMS.setFont(new java.awt.Font("Lucida Grande", 0, 12));
        checkRMS.setText("RMS");

        checkCentroid.setFont(new java.awt.Font("Lucida Grande", 0, 12));
        checkCentroid.setText("Centroid");

        checkFlux.setFont(new java.awt.Font("Lucida Grande", 0, 12));
        checkFlux.setText("Flux");

        checkRolloff.setFont(new java.awt.Font("Lucida Grande", 0, 12));
        checkRolloff.setText("Rolloff");

        jLabel6.setFont(new java.awt.Font("Lucida Grande", 0, 12));
        jLabel6.setText("Rate / Hop size (ms):");

        textAudioRate.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter(new java.text.DecimalFormat("#0"))));
        textAudioRate.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                textAudioRateActionPerformed(evt);
            }
        });
        textAudioRate.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
            public void propertyChange(java.beans.PropertyChangeEvent evt) {
                textAudioRatePropertyChange(evt);
            }
        });

        jLabel3.setFont(new java.awt.Font("Lucida Grande", 0, 12));
        jLabel3.setText("FFT size");

        textFftSize.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter(new java.text.DecimalFormat("#0"))));
        textFftSize.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                textFftSizeActionPerformed(evt);
            }
        });
        textFftSize.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
            public void propertyChange(java.beans.PropertyChangeEvent evt) {
                textFftSizePropertyChange(evt);
            }
        });

        jLabel4.setFont(new java.awt.Font("Lucida Grande", 0, 12));
        jLabel4.setText("Window size");

        textWindowSize.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter(new java.text.DecimalFormat("#0"))));
        textWindowSize.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                textWindowSizeActionPerformed(evt);
            }
        });
        textWindowSize.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
            public void propertyChange(java.beans.PropertyChangeEvent evt) {
                textWindowSizePropertyChange(evt);
            }
        });

        jLabel5.setFont(new java.awt.Font("Lucida Grande", 0, 12));
        jLabel5.setText("type");

        comboWindowType.setFont(new java.awt.Font("Lucida Grande", 0, 12));
        comboWindowType.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Hamming", "Hann", "Rectangular" }));
        comboWindowType.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                comboWindowTypeActionPerformed(evt);
            }
        });

        org.jdesktop.layout.GroupLayout jPanel1Layout = new org.jdesktop.layout.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(jPanel1Layout.createSequentialGroup()
                        .add(checkFFT)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
                        .add(jLabel3)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(textFftSize, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 63, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
                        .add(jLabel4)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(textWindowSize, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 63, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                    .add(jPanel1Layout.createSequentialGroup()
                        .add(jLabel6)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(textAudioRate, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 63, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                        .add(146, 146, 146)
                        .add(jLabel5)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(comboWindowType, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                    .add(jPanel1Layout.createSequentialGroup()
                        .add(checkRMS)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
                        .add(checkCentroid)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
                        .add(checkFlux)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
                        .add(checkRolloff)))
                .add(0, 39, Short.MAX_VALUE))
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(org.jdesktop.layout.GroupLayout.TRAILING, jPanel1Layout.createSequentialGroup()
                .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(checkRMS)
                    .add(checkCentroid)
                    .add(checkFlux)
                    .add(checkRolloff))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
                .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(checkFFT)
                    .add(jLabel3)
                    .add(textFftSize, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .add(jLabel4)
                    .add(textWindowSize, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .add(jLabel5)
                    .add(comboWindowType, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(jLabel6)
                    .add(textAudioRate, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)))
        );

        checkTrackpad.setText("Trackpad / mouse");

        checkMotion.setText("Laptop motion sensor with extraction rate of");

        checkHid.setText("HID device");

        jButton1.setText("Configure...");
        jButton1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton1ActionPerformed(evt);
            }
        });

        labelHidDescription.setText("jLabel1");

        checkCustomChuck.setText("Custom chuck feature extractor with");
        checkCustomChuck.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                checkCustomChuckActionPerformed(evt);
            }
        });

        labelCustomChuck2.setText("features");

        checkCustomOSC.setText("Custom OSC feature extractor with");

        textNumCustomOSCFeatures.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter(new java.text.DecimalFormat("#0"))));

        jLabel7.setText("features");

        checkWebcam.setText("Webcam:");

        buttonGroup1.add(radioWebcamEdge);
        radioWebcamEdge.setText("Edge tracking");

        buttonGroup1.add(radioWebcamColor);
        radioWebcamColor.setText("Color tracking");

        buttonLoad.setText("Load settings from file...");
        buttonLoad.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonLoadActionPerformed(evt);
            }
        });

        buttonSave.setText("Save settings to file...");
        buttonSave.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonSaveActionPerformed(evt);
            }
        });

        buttonUndo.setText("Undo changes");
        buttonUndo.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonUndoActionPerformed(evt);
            }
        });

        buttonGo.setText("Go!");
        buttonGo.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonGoActionPerformed(evt);
            }
        });

        textMotionExtractionRate.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter(new java.text.DecimalFormat("#0"))));
        textMotionExtractionRate.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                textMotionExtractionRateActionPerformed(evt);
            }
        });
        textMotionExtractionRate.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
            public void propertyChange(java.beans.PropertyChangeEvent evt) {
                textMotionExtractionRatePropertyChange(evt);
            }
        });

        jLabel1.setText("ms");

        labelFeatureStatus.setText("No feature configuration set.");

        buttonAddMeta.setText("Add meta-features from these features...");
        buttonAddMeta.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                buttonAddMetaActionPerformed(evt);
            }
        });

        labelNumCustomChuckFeatures.setText("100");

        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .add(47, 47, 47)
                .add(labelHidDescription, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 549, Short.MAX_VALUE))
            .add(layout.createSequentialGroup()
                .addContainerGap()
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(jPanel1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .add(layout.createSequentialGroup()
                        .add(checkWebcam)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(radioWebcamEdge)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
                        .add(radioWebcamColor))
                    .add(layout.createSequentialGroup()
                        .add(checkHid)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(jButton1))
                    .add(layout.createSequentialGroup()
                        .add(checkCustomChuck)
                        .add(9, 9, 9)
                        .add(labelNumCustomChuckFeatures)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(labelCustomChuck2))
                    .add(layout.createSequentialGroup()
                        .add(checkCustomOSC)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(textNumCustomOSCFeatures, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 45, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(jLabel7))
                    .add(layout.createSequentialGroup()
                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                            .add(checkTrackpad)
                            .add(checkMotion))
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(textMotionExtractionRate, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 45, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(jLabel1)))
                .addContainerGap())
            .add(layout.createSequentialGroup()
                .addContainerGap()
                .add(buttonGo)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(labelFeatureStatus, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 379, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(116, Short.MAX_VALUE))
            .add(layout.createSequentialGroup()
                .addContainerGap()
                .add(buttonLoad)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(buttonSave)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
                .add(buttonUndo)
                .addContainerGap(61, Short.MAX_VALUE))
            .add(layout.createSequentialGroup()
                .addContainerGap()
                .add(buttonAddMeta)
                .addContainerGap(277, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .add(32, 32, 32)
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
                    .add(layout.createSequentialGroup()
                        .add(checkTrackpad)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(checkMotion))
                    .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                        .add(textMotionExtractionRate, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                        .add(jLabel1)))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(checkHid)
                    .add(jButton1))
                .add(1, 1, 1)
                .add(labelHidDescription, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 16, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(checkCustomChuck)
                    .add(labelCustomChuck2)
                    .add(labelNumCustomChuckFeatures))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(checkCustomOSC)
                    .add(textNumCustomOSCFeatures, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                    .add(jLabel7))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(checkWebcam)
                    .add(radioWebcamEdge)
                    .add(radioWebcamColor))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(jPanel1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.UNRELATED)
                .add(buttonAddMeta)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 52, Short.MAX_VALUE)
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(buttonLoad)
                    .add(buttonSave)
                    .add(buttonUndo))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(buttonGo)
                    .add(labelFeatureStatus))
                .addContainerGap())
        );
    }// </editor-fold>//GEN-END:initComponents

    private void textFftSizeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_textFftSizeActionPerformed
}//GEN-LAST:event_textFftSizeActionPerformed

    private void textFftSizePropertyChange(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_textFftSizePropertyChange
}//GEN-LAST:event_textFftSizePropertyChange

    private void textAudioRateActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_textAudioRateActionPerformed
}//GEN-LAST:event_textAudioRateActionPerformed

    private void textAudioRatePropertyChange(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_textAudioRatePropertyChange
}//GEN-LAST:event_textAudioRatePropertyChange

    private void textWindowSizeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_textWindowSizeActionPerformed
}//GEN-LAST:event_textWindowSizeActionPerformed

    private void textWindowSizePropertyChange(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_textWindowSizePropertyChange
}//GEN-LAST:event_textWindowSizePropertyChange

    private void comboWindowTypeActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_comboWindowTypeActionPerformed
    }//GEN-LAST:event_comboWindowTypeActionPerformed

    private void checkCustomChuckActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_checkCustomChuckActionPerformed
}//GEN-LAST:event_checkCustomChuckActionPerformed

    private void textMotionExtractionRateActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_textMotionExtractionRateActionPerformed
}//GEN-LAST:event_textMotionExtractionRateActionPerformed

    private void textMotionExtractionRatePropertyChange(java.beans.PropertyChangeEvent evt) {//GEN-FIRST:event_textMotionExtractionRatePropertyChange
}//GEN-LAST:event_textMotionExtractionRatePropertyChange
    PropertyChangeListener currentHidSetupChangeListener = new PropertyChangeListener() {

        public void propertyChange(PropertyChangeEvent evt) {
            currentHidSetupPropertyChanged(evt);
        }
    };

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed
        HidSetupForm p = new HidSetupForm(this);
        p.setVisible(true);
    }//GEN-LAST:event_jButton1ActionPerformed

    private void buttonLoadActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonLoadActionPerformed
        File file = Util.findLoadFile(FeatureConfiguration.getFileExtension(),
                FeatureConfiguration.getFileTypeDescription(),
                FeatureConfiguration.getDefaultLocation(),
                this);
        if (file != null) {
            FeatureConfiguration newF = null;

            try {
                newF = FeatureConfiguration.readFromFile(file);
            } catch (Exception ex) {
                System.out.println("Unable to load feature configuration from file");
                Logger.getLogger(FeatureConfigurationPanel.class.getName()).log(Level.SEVERE, null, ex);
            }
            if (newF != null) {
                setFormFromConfiguration(newF); //TODO: Problematic: What do we do w/ backup?; make usre to deal with hid there
                Util.setLastFile(FeatureConfiguration.getFileExtension(), file);
            }
        }
    }//GEN-LAST:event_buttonLoadActionPerformed

    private void buttonSaveActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonSaveActionPerformed
        try {
            FeatureConfiguration featureConfiguration = setConfigurationFromForm();
            featureConfiguration.validate();
            File file = Util.findSaveFile(FeatureConfiguration.getFileExtension(),
                    FeatureConfiguration.getFileTypeDescription(),
                    FeatureConfiguration.getDefaultLocation(),
                    this);
            if (file != null) {
                try {
                    featureConfiguration.writeToFile(file);
                    Util.setLastFile(FeatureConfiguration.getFileExtension(), file);
                } catch (Exception ex) {
                    Logger.getLogger(FeatureConfigurationPanel.class.getName()).log(Level.INFO, null, ex);
                    System.out.println("Could not save feature configuration to file");
                }
            }
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(this, ex.getMessage(), "Invalid feature configuration; cannot save.", JOptionPane.ERROR_MESSAGE);
        }
    }//GEN-LAST:event_buttonSaveActionPerformed

    private void clearForm() {
        setFormFromConfiguration(new FeatureConfiguration());
    }

    private void buttonUndoActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonUndoActionPerformed
        //  setFormFromConfiguration(backup);
        if (WekinatorInstance.getWekinatorInstance().getFeatureConfiguration() != null) {
            setFormFromConfiguration(WekinatorInstance.getWekinatorInstance().getFeatureConfiguration());
        } else {
            clearForm();
        }

    }//GEN-LAST:event_buttonUndoActionPerformed

    private void buttonGoActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonGoActionPerformed
        FeatureConfiguration featureConfiguration = null;
        try {
            //Zeroth, check this is valid
            featureConfiguration = setConfigurationFromForm();
            featureConfiguration.validate();

        } catch (Exception ex) {
            Logger.getLogger(FeatureConfigurationPanel.class.getName()).log(Level.INFO, null, ex);
            JOptionPane.showMessageDialog(this, ex.getMessage(), "Invalid feature configuration", JOptionPane.ERROR_MESSAGE);
            return;
        }


        //First, prompt the user to overwrite
        //TODO: what does this have to do with chuck system?
        //TODO: allow to continue if # features same?
        //Ideally need a map ID kind of thing here... or at min a name/hash-based way of keeping track of feats, independent of global order?
        //This is low priority: min behavior should just destroy models if feats change AT ALL (i.e. names & nums not identical)
        //Best hting here is to compare names of features; if they match, then we're really identical.

        //TODO ABC: We want to be able to re-set feature config to an identical config
        //when chuck system needs to be reconnected!
        //no user prompt necessary, but def must trigger chuck OSC communication AND re-enable panels when appropriate.

        boolean areEqual = FeatureConfiguration.equal(featureConfiguration, WekinatorInstance.getWekinatorInstance().getFeatureConfiguration());

        if (!areEqual && ChuckSystem.getChuckSystem().state == ChuckSystem.ChuckSystemState.CONNECTED_AND_VALID) { //TODO: put this check back in; make sure appropriate panels still visible when they are equal and we don't change.

            if (WekinatorInstance.getWekinatorInstance().getFeatureConfiguration() != null) {
                int lResponse = JOptionPane.showConfirmDialog(this, "Are you sure you want to change your feature configuration?\n" + "This will destroy any existing trained models...", "", JOptionPane.YES_NO_OPTION);
                if (lResponse != JOptionPane.YES_OPTION) {
                    return;
                } else {

                    WekinatorInstance.getWekinatorInstance().setFeatureConfiguration(featureConfiguration);
                    labelFeatureStatus.setText("Feature configuration set; using " + featureConfiguration.getNumFeaturesEnabled() + " features.");
                    return;
                }
            }
            // }
            //Possible problem here: what if not "equal" per se but still need to refresh chuck? Does equality work with hid change, fft size change, motion rate change, etc.?
        } else if (ChuckSystem.getChuckSystem().state != ChuckSystem.ChuckSystemState.CONNECTED_AND_VALID) {
            //else {
            //Then, set backup to the current configuration, and set the WekInst current to it as well
            WekinatorInstance.getWekinatorInstance().setFeatureConfiguration(featureConfiguration);
            labelFeatureStatus.setText("Feature configuration set; using " + featureConfiguration.getNumFeaturesEnabled() + " features.");

        }
    }//GEN-LAST:event_buttonGoActionPerformed

    private void buttonAddMetaActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_buttonAddMetaActionPerformed
        try {
            //Zeroth, check this is valid
            FeatureConfiguration fc = setConfigurationFromForm();
            //ABC: add metafeatures existing.

            /*   HidSetup tmptmp = new HidSetup();
            tmptmp.usable = true;
            featureConfiguration.setHidSetup(tmptmp); */
            fc.validate();
            mf = new FeatureConfigurationMetaFrame(fc, this);
            mf.setVisible(true);
        } catch (Exception ex) {
            Logger.getLogger(FeatureConfigurationPanel.class.getName()).log(Level.INFO, null, ex);
            JOptionPane.showMessageDialog(this, ex.getMessage(), "Invalid feature configuration; fix before adding meta features", JOptionPane.ERROR_MESSAGE);
            return;
        }
}//GEN-LAST:event_buttonAddMetaActionPerformed
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton buttonAddMeta;
    private javax.swing.JButton buttonGo;
    private javax.swing.ButtonGroup buttonGroup1;
    private javax.swing.JButton buttonLoad;
    private javax.swing.JButton buttonSave;
    private javax.swing.JButton buttonUndo;
    private javax.swing.JCheckBox checkCentroid;
    private javax.swing.JCheckBox checkCustomChuck;
    private javax.swing.JCheckBox checkCustomOSC;
    private javax.swing.JCheckBox checkFFT;
    private javax.swing.JCheckBox checkFlux;
    private javax.swing.JCheckBox checkHid;
    private javax.swing.JCheckBox checkMotion;
    private javax.swing.JCheckBox checkRMS;
    private javax.swing.JCheckBox checkRolloff;
    private javax.swing.JCheckBox checkTrackpad;
    private javax.swing.JCheckBox checkWebcam;
    private javax.swing.JComboBox comboWindowType;
    private javax.swing.JButton jButton1;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JLabel jLabel7;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JLabel labelCustomChuck2;
    private javax.swing.JLabel labelFeatureStatus;
    private javax.swing.JLabel labelHidDescription;
    private javax.swing.JLabel labelNumCustomChuckFeatures;
    private javax.swing.JRadioButton radioWebcamColor;
    private javax.swing.JRadioButton radioWebcamEdge;
    private javax.swing.JFormattedTextField textAudioRate;
    private javax.swing.JFormattedTextField textFftSize;
    private javax.swing.JFormattedTextField textMotionExtractionRate;
    private javax.swing.JFormattedTextField textNumCustomOSCFeatures;
    private javax.swing.JFormattedTextField textWindowSize;
    // End of variables declaration//GEN-END:variables

    protected void updateHidChangeListener(HidSetup o, HidSetup n, PropertyChangeListener l) {
        if (o != null) {
            o.removePropertyChangeListener(l);
        }
        if (n != null) {
            n.addPropertyChangeListener(l);
        }
    }

    protected final void setHidSetup(HidSetup h) {
        HidSetup oldSetup = hidSetup;
        hidSetup = h;
        if (hidSetup != null) {
            labelHidDescription.setText(hidSetup.getDescription());
        } else {
            labelHidDescription.setText("No HID configured.");
        }
        updateHidChangeListener(oldSetup, hidSetup, currentHidSetupChangeListener);
    }

    public void setFormFromConfiguration(FeatureConfiguration featureConfiguration) {
        if (featureConfiguration != null) {
            setHidSetup(featureConfiguration.getHidSetup());
        } else {
            setHidSetup(null);
        }

        //PROBLEM: we're discarding this featureConfiguration and relying on the form...
        //we still need it, or its metafeature info in a new representation, to load metafeature pane.
        //this is inefficient but should owrk:

        metaFeatureMatrix = featureConfiguration.getMetaFeatureMatrix();

        //      HashMap<String, ArrayList<LinkedList<MetaFeature>>> allMetaFeatures = new HashMap<String, ArrayList<LinkedList<MetaFeature>>>();
        // featureConfiguration.setMetaFeaturesFromMatrix(allMetaFeatures)

        textAudioRate.setValue(new Integer(featureConfiguration.getAudioExtractionRate()));
        textFftSize.setValue(new Integer(featureConfiguration.getFftSize()));
        textWindowSize.setValue(new Integer(featureConfiguration.getFftWindowSize()));
        textMotionExtractionRate.setValue(new Integer(featureConfiguration.getMotionSensorExtractionRate()));
        //textNumCustomChuckFeatures.setValue(new Integer(featureConfiguration.getNumCustomChuckFeatures()));
        textNumCustomOSCFeatures.setValue(new Integer(featureConfiguration.getNumCustomOscFeatures()));
        if (featureConfiguration.processingExtractorType == FeatureConfiguration.ProcessingExractorType.DOWNSAMPLED_100) {
            radioWebcamEdge.setSelected(true);
        } else if (featureConfiguration.processingExtractorType == FeatureConfiguration.ProcessingExractorType.COLOR_6) {
            radioWebcamColor.setSelected(true);
        }

        checkCentroid.setSelected(featureConfiguration.isUseCentroid());
        checkCustomChuck.setSelected(featureConfiguration.isUseCustomChuckFeatures());
        checkCustomOSC.setSelected(featureConfiguration.isUseCustomOscFeatures());
        checkFFT.setSelected(featureConfiguration.isUseFFT());
        checkFlux.setSelected(featureConfiguration.isUseFlux());
        checkMotion.setSelected(featureConfiguration.isUseMotionSensor());
        checkHid.setSelected(featureConfiguration.isUseOtherHid());

        checkWebcam.setSelected(featureConfiguration.isUseProcessing());
        checkTrackpad.setSelected(featureConfiguration.isUseTrackpad());
        checkRMS.setSelected(featureConfiguration.isUseRMS());
        checkRolloff.setSelected(featureConfiguration.isUseRolloff());

        switch (featureConfiguration.getWindowType()) {
            case HAMMING:
                comboWindowType.setSelectedItem("Hamming");
                break;
            case HANN:
                comboWindowType.setSelectedItem("Hann");
                break;
            case RECTANGULAR:
                comboWindowType.setSelectedItem("Rectangular");
                break;
            default:
                System.out.println("problem");
        }
    }

    protected FeatureConfiguration setConfigurationFromForm() throws Exception {
        FeatureConfiguration featureConfiguration = null;
        try {
            featureConfiguration = new FeatureConfiguration();
            if (hidSetup != null) {
                featureConfiguration.setHidSetup(hidSetup);
            }
            try {
                featureConfiguration.setAudioExtractionRate(Integer.parseInt(textAudioRate.getText()));
            } catch (Exception ex) {
                featureConfiguration.setAudioExtractionRate(100);
            }
            try {
                featureConfiguration.setFftSize(Integer.parseInt(textFftSize.getText()));
            } catch (Exception ex) {
                featureConfiguration.setFftSize(1024);
            }

            try {
                featureConfiguration.setFftWindowSize(Integer.parseInt(textWindowSize.getText()));
            } catch (Exception ex) {
                featureConfiguration.setFftWindowSize(256);
            }
            //featureConfiguration.setHidSetup not necessary: would've done this regardless
            try {
                featureConfiguration.setMotionSensorExtractionRate(Integer.parseInt(textMotionExtractionRate.getText()));
            } catch (Exception ex) {
                featureConfiguration.setMotionSensorExtractionRate(100);
            }

            try {
                featureConfiguration.setNumCustomChuckFeatures(WekinatorInstance.getWekinatorInstance().getConfiguration().getNumCustomChuckFeaturesExtracted());
                //featureConfiguration.setNumCustomChuckFeatures(Integer.parseInt(textNumCustomChuckFeatures.getText()));
            } catch (Exception ex) {
                featureConfiguration.setNumCustomChuckFeatures(0);
            }

            try {
                featureConfiguration.setNumCustomOscFeatures(Integer.parseInt(textNumCustomOSCFeatures.getText()));
            } catch (Exception ex) {
                featureConfiguration.setNumCustomOscFeatures(0);
            }
            if (radioWebcamEdge.getModel().isSelected()) {
                featureConfiguration.setProcessingExtractorType(FeatureConfiguration.ProcessingExractorType.DOWNSAMPLED_100);
            } else if (radioWebcamColor.getModel().isSelected()) {
                featureConfiguration.setProcessingExtractorType(FeatureConfiguration.ProcessingExractorType.COLOR_6);
            }


            featureConfiguration.setUseCentroid(checkCentroid.isSelected());
            featureConfiguration.setUseCustomChuckFeatures(checkCustomChuck.isSelected());
            featureConfiguration.setUseCustomOscFeatures(checkCustomOSC.isSelected());
            featureConfiguration.setUseFFT(checkFFT.isSelected());
            featureConfiguration.setUseFlux(checkFlux.isSelected());
            featureConfiguration.setUseMotionSensor(checkMotion.isSelected());

            featureConfiguration.setUseOtherHid(checkHid.isSelected());
            //TODO: Handle hid changing when loading different feature sets.
            featureConfiguration.setUseProcessing(checkWebcam.isSelected());
            featureConfiguration.setUseRMS(checkRMS.isSelected());
            featureConfiguration.setUseRolloff(checkRolloff.isSelected());
            featureConfiguration.setUseTrackpad(checkTrackpad.isSelected());


            String windowString = (String) comboWindowType.getSelectedItem();
            if (windowString.equals("Hamming")) {
                featureConfiguration.setWindowType(WindowType.HAMMING);
            } else if (windowString.equals("Hann")) {
                featureConfiguration.setWindowType(WindowType.HANN);
            } else if (windowString.equals("Rectangular")) {
                featureConfiguration.setWindowType(WindowType.RECTANGULAR);
            } else {
                System.out.println("Problem");
                //TODO: log severe
            }

            if (metaFeatureMatrix != null) {
                featureConfiguration.setMetaFeaturesFromMatrix(metaFeatureMatrix);
            }
        } catch (Exception ex) {
            System.out.println("STUPID");
            ex.printStackTrace();
            System.out.println(ex.getMessage());
            throw new Exception("Invalid formatting in number box" + ex.getMessage());
        }
        return featureConfiguration;

    }

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {


                // ChuckConfigurationForm panel = new ChuckConfigurationForm(c);

                // panel.setVisible(true);
                JFrame frame = new JFrame();
                FeatureConfigurationPanel panel = new FeatureConfigurationPanel();
                FeatureConfiguration fc = new FeatureConfiguration();
                //    fc.setWindowType(WindowType.RECTANGULAR);
                //   panel.setFormFromConfiguration(fc);
                //fc.setNumCustomChuckFeatures(10);
                //fc.setTmp(53);
                //panel.getFeatureConfiguration1().setTmp(53);
                //panel.getFeatureConfiguration1().setNumCustomOscFeatures(25);
                frame.add(panel);
                frame.setVisible(true);


                Console c = Console.getInstance();

                c.setVisible(true);
                try {
                    OscHandler.getOscHandler().startHandshake();
                } catch (IOException ex) {
                    System.out.println("Handshake failed -- no chuck for you!");
                    Logger.getLogger(FeatureConfigurationPanel.class.getName()).log(Level.SEVERE, null, ex);
                }


            }
        });
    }

    private void currentHidSetupPropertyChanged(PropertyChangeEvent evt) {
        System.out.println("Received hid change event");
        labelHidDescription.setText(hidSetup.getDescription());
    }
}
